#ifndef MSGPARSER_H
#define MSGPARSER_H

#pragma once

/**************************************************************************************************************************
 * 类名：MsgParser
 * 作者：YuLijun
 * 日期：
 * 说明：解析接收到的报文。一次性接收到的内容用processBuffer处理，
 *       已经分解组合好的（!AIVDM,1,1,...,0*2A）语句用parse处理。
 *       单例模式，外部直接用 MSGPARSER->  使用即可，可以放到线程中。
 ***************************************************************************************************************************/

#include <QObject>
#include "MsgStruct.h"
#include "sixbitstring.h"
#include "MSentenceManage.h"
#include <QMap>

namespace ns_yht
{

#define MSGPARSER MsgParser::instance()

#define MAX_MESSAGE_LEN (10 * 82)
    typedef unsigned char BYTE;

    class MsgParser : public QObject
    {
        Q_OBJECT

    public:
        MsgParser();
        ~MsgParser();
        static MsgParser *instance();

        void setPostback(bool postBack);

        void *getLastResult();

    public slots:
        /**
         * 处理已经分解组合好的（!AIVDM,1,1,...,0*2A）语句
         **/
        void parse(const QByteArray &msg);

        /**
         * 处理直接从接口收到的内容
         **/
        void processBuffer(const QByteArray &buffer);

        void detectDevices();

    signals:
        void deviceLost(int deviceId);
        void deviceRecovered(int deviceId);

        void zdaFinished(ZDA *zda);
        void ais1Finished(AIS_1 *ais, bool vdo);
        void ais5Finished(AIS_5 *ais, bool vdo);
        void ais4Finished(AIS_4 *ais, bool vdo);
        void ais14Finished(AIS_14 *ais, bool vdo);
        void ais18Finished(AIS_18 *ais, bool vdo);
        void ais24Finished(AIS_24 *ais, bool vdo);

        void HDTFinished(double depth);
        void HDGFinished(HDG *hdg);
        void DBTFinished(double);
        void DPTFinished(DPT *dpt);

        void ALRFinished(ALR *alr);

        void GGAFinished(GGA *gga);
        void GLLFinished(GLL *gll);
        void RMCFinished(RMC *rmc);
        void VTGFinished(VTG *vtg);
        void RMBFinished(RMB *rmb);
        void GNSFinished(GNS *gns);

        void TCIFinished(TCI *tci);
        void TTMFinished(TTM *ttm);
        void TLLFinished(TLL *tll);

        void posStateChange(int state);

        void postbackData(const QByteArray &msg);

    private:
        int getInt(int start, int len, bool signed_flag = false);
        int getStr(int start, int bit_len, char *dest, int max_len);

        TalkType parseTalkId(const QByteArray &msg);
        void parseACK(const QByteArray &msg);
        void parseALR(const QByteArray &msg);
        void parseZDA(const QByteArray &msg);
        void parseAIS(const QByteArray &msg, bool vdo);

        void parseAIS_1(SixBitString &sb, bool vdo);
        void parseAIS_5(SixBitString &sb, bool vdo);
        void parseAIS_4(SixBitString &sb, bool vdo);
        void parseAIS_14(SixBitString &sb, bool vdo);
        void parseAIS_18(SixBitString &sb, bool vdo);
        void parseAIS_24(SixBitString &sb, bool vdo);

        void parseHDT(const QByteArray &msg);
        void parseHDG(const QByteArray &msg);
        void parseDPT(const QByteArray &msg);
        void parseDBT(const QByteArray &msg);

        void parseACN(const QByteArray &msg);
        void parseALC(const QByteArray &msg);
        void parseALF(const QByteArray &msg);

        void parseGGA(const QByteArray &msg);
        void parseGLL(const QByteArray &msg);
        void parseRMC(const QByteArray &msg);
        void parseVTG(const QByteArray &msg);
        void parseRMB(const QByteArray &msg);
        void parseGNS(const QByteArray &msg);

        void parseTCI(const QByteArray &msg);

        void parseTTM(const QByteArray &msg);
        void parseTLL(const QByteArray &msg);

        int getSatelliteType(const QByteArray &code);

    private:
        int XCharToNum(char xch);

        QByteArray SIX_BIT_ASCII;
        QByteArray SIX_BIT_ARMOR;

        BYTE bitBytes[MAX_MESSAGE_LEN];

        QByteArray m_lastMsg;
        MSentenceManage msManage;

        qint64 m_BDLastTime{-9999};
        qint64 m_GPLastTime{-9999};
        qint64 m_AISLastTime{-9999};

        QMap<int, qint64> m_deviceUpdateTime;
        QVector<int> m_lostedDevices;
        int state{-1}; // -1:未知，0:BD，1：GP，2：AIS

        bool m_postback{false};

        void *m_lastResult{nullptr}; // 最近一次解析结果，用于单元测试
    };

} // namespace ns_yht
#endif
